package com.ecnu.sei.app.teacher;

import java.util.HashSet;
import java.util.Set;

import com.ecnu.sei.app.course.AbstractCourse;
import com.ecnu.sei.app.course.ExamInfo;
import com.ecnu.sei.app.resources.Time;

public abstract class AbstractTeacher {

  protected String id;
  protected String name;
  protected int limit;
  protected int count; // number of proctors
  protected Set<Time> timeTable = new HashSet<Time>(); // proctoring time
  protected Set<AbstractCourse> courses = new HashSet<AbstractCourse>(); // proctoring courses
  protected Set<Time> leaves = new HashSet<Time>();    // take leave

  
  public AbstractTeacher() {}

  public AbstractTeacher(String id, String name) {
    this(id, name, 4, new HashSet<Time>());
  }

  public AbstractTeacher(String id, String name, Set<Time> leaves) {
    this(id, name, 4, leaves);  
  }

 
  public AbstractTeacher(String id, String name, int limit, Set<Time> leaves) {
    
    this.id = id;
    this.name = name;
    this.limit = limit;
    this.count = 0;
    this.leaves = leaves;
  }
  
  public String getId() {
    return id;
  }
  
  public String getName() {
    return name;
  }

  public int getCount() {
    return count;
  }

  public int getLimit() {
    return limit;
  }
  
  public String getTimeTable() {
    StringBuilder sb = new StringBuilder();
    for (AbstractCourse proctored : courses) {
      sb.append("{" + proctored.getCourseInfo().getCourseName() + ":" + proctored.getExamTime() + "}");
    }
    return sb.toString();
  }
  
  public void addProctor(AbstractCourse course) {
    courses.add(course);
    ExamInfo examInfo = course.getCourseInfo().getExamInfo();
    timeTable.add(examInfo.getTime());
    count++;
  }

  public void addLeave(Time time) {
    leaves.add(time);
  }

  public AbstractTeacher setName(String name) {
    this.name = name;
    return this;
  }

 /* public AbstractTeacher setLeaves(Set<Time> leaves) {
    this.leaves = leaves;
    return this;
  }
  */
  
  public AbstractTeacher setLeaves(Set<Time> leaves) {
    this.leaves = leaves;
    return this;
  }
  
  public AbstractTeacher setLimit(int limit) {
	  this.limit = limit;
	  return this;
  }

  /*  common rules:
   * 
   *  1. not exceed limit
   *  2. not take leave
   *  3. not already proctor exam
   *  4. not proctor at both DayHour.MORN_TWO and DayHour.AFTN_ONE
   */

  public boolean isAvailableFor(AbstractCourse course) {
    ExamInfo examInfo = course.getCourseInfo().getExamInfo();
    Time time = examInfo.getTime();

    // not exceed limit
    if (isExceedLimit()) {
      return false;
    }

    // not take leave
    if (isTakeLeave(time)) {
      return false;
    }


    // not already proctor exam or 
    // at both DayHour.MORN_TWO and DayHour.AFTN_ONE
    if (timeTable.contains(time)) {
      return false;
    }  else {  
      for (Time t : timeTable) {
        if (t.isContHalfDay(time)) {
          return false;
        }
      }
    }

    return true;
  }

  public boolean isExceedLimit() {
    return count >= limit;
  }
  
  private boolean isTakeLeave(Time time) {
    return leaves.contains(time);
  }

  public void clearProctor() {
    timeTable.clear();
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    AbstractTeacher other = (AbstractTeacher) obj;
    if (id == null) {
      if (other.id != null)
        return false;
    } else if (!id.equals(other.id))
      return false;
    return true;
  }

  @Override
  public String toString() {
    return "AbstractTeacher [name=" + name + "]";
  }
  
  
  
}
